package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.builder.ExhibitorFeign;
import com.eastfair.builder.dto.ExhibitorDTO;
import com.eastfair.builder.enumeration.ExhibitorSettleStatusEnum;
import com.eastfair.builder.vo.ExhibitorVO;
import com.eastfair.common.api.PaymentRecordFeign;
import com.eastfair.common.api.TransactionFeign;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.context.StaticContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.home.api.HomeMsgFeign;
import com.eastfair.messagecenter.util.SendMsgUtil;
import com.eastfair.pay.dto.PaymentRecordDTO;
import com.eastfair.pay.dto.TransactionDTO;
import com.eastfair.pay.dto.TransactionOrderDTO;
import com.eastfair.pay.enumeration.TransactionOrderOrderStatusEnum;
import com.eastfair.pay.enumeration.TransactionOrderOrderTypeEnum;
import com.eastfair.pay.enums.*;
import com.eastfair.projectcore.enumeration.MenuAffiliationEnum;
import com.eastfair.venueservice.dao.ExhibitionSettlementMapper;
import com.eastfair.venueservice.dto.*;
import com.eastfair.venueservice.entity.*;
import com.eastfair.venueservice.enumeration.*;
import com.eastfair.venueservice.enums.SettlementCollectTypeEnum;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.*;
import com.eastfair.venueservice.vo.ExhibitionSettlementDetailVO;
import com.eastfair.venueservice.vo.ExhibitionSettlementVO;
import com.eastfair.venueservice.vo.ServiceBookingVO;
import com.eastfair.venueservice.vo.ServiceProviderVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.eastfair.venueservice.consts.CommonConstants.COMMON_IGNORE_PROPERTIES;

/**
 * <p>
 * 业务实现类
 * 结算记录
 * </p>
 *
 * @author linan
 * @date 2023-01-10
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ExhibitionSettlementServiceImpl extends SuperServiceImpl<ExhibitionSettlementMapper, ExhibitionSettlement> implements ExhibitionSettlementService {

    public static final String SETTLEMENT_NO = "settlement_no";
    public static final String JS = "JS";

    @Value("${pay.payee.venue-manage}")
    private String venueManagePayee;
    @Resource
    private ExhibitionServiceProviderService exhibitionServiceProviderService;
    @Resource
    private ServiceProviderService serviceProviderService;
    @Resource
    private WorkOrderService workOrderService;
    @Resource
    private ServiceBookingService serviceBookingService;
    @Resource
    private ExhibitionManageService exhibitionManageService;
    @Resource
    private ServiceOrderService serviceOrderService;
    @Resource
    private HomeServiceOrderService homeServiceOrderService;
    @Resource
    private ExhibitorFeign exhibitorFeign;
    @Resource
    private PaymentRecordFeign paymentRecordFeign;
    @Resource
    private SendMsgUtil sendMsgUtil;
    @Resource
    private HomeMsgFeign homeMsgFeign;
    @Resource
    private TransactionFeign transactionFeign;
    @Resource
    private VenueManageTransactionOrderService venueManageTransactionOrderService;
    @Resource(name = "threadPoolTaskExecutor")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Resource
    private ExhibitionSettlementDetailService exhibitionSettlementDetailService;

    @Resource
    private VenueRepairServiceOrderService venueRepairServiceOrderService;

    @Resource
    private HomeRepairServiceOrderService homeRepairServiceOrderService;

    @Resource
    private WorkOvertimeService workOvertimeService;

    @Resource
    private BondManageService bondManageService;

    @Resource
    private HomeBondManageService homeBondManageService;

    @Resource
    private ViolationRecordService violationRecordService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ExhibitionSettlement> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }


    @Override
    protected R<Boolean> handlerSave(ExhibitionSettlement model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        return R.successDef();
    }

    @Override
    public List<ExhibitionSettlementVO> queryExhibitionSettlement(ExhibitionSettlementDTO query) {
        List<ExhibitionSettlement> list = list(new QueryWrapper<ExhibitionSettlement>().lambda()
                .eq(ExhibitionSettlement::getIsDeleted, BusinessConstant.DELETE_NO)
                // 开票状态
                .eq(Objects.nonNull(query.getInvoicingStatus()), ExhibitionSettlement::getInvoicingStatus, query.getInvoicingStatus())
                // 退款状态
                .eq(Objects.nonNull(query.getRefundStatus()), ExhibitionSettlement::getRefundStatus, query.getRefundStatus())
                .eq(Objects.nonNull(query.getCompanyId()), ExhibitionSettlement::getCompanyId, query.getCompanyId())
                .eq(ExhibitionSettlement::getExhibitionManageId, query.getExhibitionManageId()));
        Map<ExhibitionSettlementCompanyTypeEnum, ExhibitionSettlement> exhibitionSettlementMap = list.stream().filter(e -> !e.getCompanyType().eq(ExhibitionSettlementCompanyTypeEnum.MATCHING_SERVICE_PROVIDER) && !e.getCompanyType().eq(ExhibitionSettlementCompanyTypeEnum.BUILD_SERVICE_PROVIDER)).collect(Collectors.toMap(ExhibitionSettlement::getCompanyType, Function.identity()));
        // 查询展会服务商
        ExhibitionServiceProviderDTO exhibitionServiceProviderDTO = new ExhibitionServiceProviderDTO();
        exhibitionServiceProviderDTO.setExhibitionManageId(query.getExhibitionManageId());
        List<ExhibitionServiceProvider> exhibitionServiceProviders = exhibitionServiceProviderService.listExhibitionServiceProvider(exhibitionServiceProviderDTO).stream().filter(e -> e.getServiceProviderType().equals(ServiceProviderTypeEnum.HOME_SERVICE_PROVIDER.getCode()) || e.getServiceProviderType().equals(ServiceProviderTypeEnum.MAIN_TRANSPORT_SERVICE_PROVIDER.getCode())).collect(Collectors.toList());
        Map<String, ExhibitionServiceProvider> exhibitionServiceProviderMap = exhibitionServiceProviders.stream().collect(Collectors.toMap(ExhibitionServiceProvider::getServiceProviderType, Function.identity()));
        ArrayList<ExhibitionSettlementVO> exhibitionSettlementVOS = new ArrayList<>();
        if (Objects.isNull(query.getCompanyId())) {
            // 主场
            ExhibitionSettlement homeExhibitionSettlement = exhibitionSettlementMap.get(ExhibitionSettlementCompanyTypeEnum.HOME_SERVICE_PROVIDER);
            ExhibitionServiceProvider home = exhibitionServiceProviderMap.get(ServiceProviderTypeEnum.HOME_SERVICE_PROVIDER.getCode());
            List<ExhibitionSettlement> exhibitionSettlements = Collections.singletonList(homeExhibitionSettlement);
            // 处理返回结果
            dealResult(exhibitionSettlementVOS, home,exhibitionSettlements);
        }
        // 处理展会名称
        for (ExhibitionSettlementVO exhibitionSettlementVO : exhibitionSettlementVOS) {
            Long exhibitionManageId = exhibitionSettlementVO.getExhibitionManageId();
            if (Objects.nonNull(exhibitionManageId)) {
                ExhibitionManage exhibitionManage = exhibitionManageService.getById(exhibitionManageId);
                if (Objects.nonNull(exhibitionManage)) {
                    exhibitionSettlementVO.setExhibitionName(exhibitionManage.getExhibitionName());
                }
            }
        }
        return exhibitionSettlementVOS;
    }

    @Override
    public List<ExhibitionSettlementVO> queryExhibitionSettlementOfBuilder(ExhibitionSettlementDTO query) {
        // 根据companyId是否存在判断是主场还是搭建商
        Long companyId = query.getCompanyId();
        // 查询已经存在的结算记录
        List<ExhibitionSettlement> list = list(new QueryWrapper<ExhibitionSettlement>().lambda()
                .eq(ExhibitionSettlement::getIsDeleted, BusinessConstant.DELETE_NO)
                // 开票状态
                .eq(Objects.nonNull(query.getInvoicingStatus()), ExhibitionSettlement::getInvoicingStatus, query.getInvoicingStatus())
                // 退款状态
                .eq(Objects.nonNull(query.getRefundStatus()), ExhibitionSettlement::getRefundStatus, query.getRefundStatus())
                // 结算状态
                .eq(Objects.nonNull(query.getSettleStatus()), ExhibitionSettlement::getSettleStatus, query.getSettleStatus())
                .eq(ExhibitionSettlement::getCompanyType, ExhibitionSettlementCompanyTypeEnum.BUILD_SERVICE_PROVIDER)
                .eq(Objects.nonNull(companyId), ExhibitionSettlement::getCompanyId, query.getCompanyId())
                .isNotNull(Objects.nonNull(companyId), ExhibitionSettlement::getSettlementNo)
                .eq(ExhibitionSettlement::getExhibitionManageId, query.getExhibitionManageId())
                .and(StrUtil.isNotEmpty(query.getKeywords()), e -> e
                        .like(ExhibitionSettlement::getSettlementNo, query.getKeywords())
                        .or().like(ExhibitionSettlement::getCompanyName, query.getKeywords())));
        return ConvertUtil.convertList(list, ExhibitionSettlementVO.class);

    }

    @Override
    public List<ExhibitionSettlementVO> queryExhibitionSettlementByCompanyId(ExhibitionSettlementDTO query) {
        // 根据companyId是否存在判断是主场还是搭建商
        Long companyId = query.getCompanyId();
        // 查询已经存在的结算记录
        List<ExhibitionSettlement> list = list(new QueryWrapper<ExhibitionSettlement>().lambda()
                .eq(ExhibitionSettlement::getIsDeleted, BusinessConstant.DELETE_NO)
                // 开票状态
                .eq(Objects.nonNull(query.getInvoicingStatus()), ExhibitionSettlement::getInvoicingStatus, query.getInvoicingStatus())
                // 退款状态
                .eq(Objects.nonNull(query.getRefundStatus()), ExhibitionSettlement::getRefundStatus, query.getRefundStatus())
                // 结算状态
                .eq(Objects.nonNull(query.getSettleStatus()), ExhibitionSettlement::getSettleStatus, query.getSettleStatus())
                .eq(ExhibitionSettlement::getCompanyType, query.getCompanyType())
                .eq(Objects.nonNull(companyId), ExhibitionSettlement::getCompanyId, query.getCompanyId())
                .isNotNull(Objects.nonNull(companyId), ExhibitionSettlement::getSettlementNo)
                .eq(Objects.nonNull(query.getExhibitionManageId()), ExhibitionSettlement::getExhibitionManageId, query.getExhibitionManageId())
                .and(StrUtil.isNotEmpty(query.getKeywords()), e -> e
                        .like(ExhibitionSettlement::getSettlementNo, query.getKeywords())
                        .or().like(ExhibitionSettlement::getCompanyName, query.getKeywords())));

        List<ExhibitionSettlementVO> exhibitionSettlementVOS = ConvertUtil.convertList(list, ExhibitionSettlementVO.class);
        // 处理展会名称
        for (ExhibitionSettlementVO exhibitionSettlementVO : exhibitionSettlementVOS) {
            Long exhibitionManageId = exhibitionSettlementVO.getExhibitionManageId();
            if (Objects.nonNull(exhibitionManageId)) {
                ExhibitionManage exhibitionManage = exhibitionManageService.getById(exhibitionManageId);
                if (Objects.nonNull(exhibitionManage)) {
                    exhibitionSettlementVO.setExhibitionName(exhibitionManage.getExhibitionName());
                }
            }
        }
        return exhibitionSettlementVOS;
    }

    @Override
    public ExhibitionSettlementVO queryDetailBySettlementNo(ExhibitionSettlementDTO query) {
        ExhibitionSettlement one = getExhibitionSettlement(query);
        if (Objects.nonNull(one)) {
            BeanUtil.copyProperties(one, query);
            if (one.getCompanyType().eq(ExhibitionSettlementCompanyTypeEnum.BUILD_SERVICE_PROVIDER)) {
                return queryExhibitionSettlementDetailOfBuilder(query);
            } else {
                return queryExhibitionSettlementDetail(query);
            }
        }
        return null;
    }

    private ExhibitionSettlement getExhibitionSettlement(ExhibitionSettlementDTO query) {
        return getOne(new QueryWrapper<ExhibitionSettlement>().lambda()
                .eq(ExhibitionSettlement::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(ExhibitionSettlement::getIsEnabled, BusinessConstant.YES)
                .eq(ExhibitionSettlement::getSettlementNo, query.getSettlementNo()));
    }

    @Override
    public List<ServiceBookingVO> queryServiceBookingListOfOrder(String settlementNo) {
        ExhibitionSettlementDTO exhibitionSettlementDTO = new ExhibitionSettlementDTO();
        exhibitionSettlementDTO.setSettlementNo(settlementNo);
        ExhibitionSettlement exhibitionSettlement = getExhibitionSettlement(exhibitionSettlementDTO);
        if (exhibitionSettlement.getCompanyType().eq(ExhibitionSettlementCompanyTypeEnum.BUILD_SERVICE_PROVIDER)) {
            ExhibitionSettlementDTO query = new ExhibitionSettlementDTO();
            query.setId(exhibitionSettlement.getId());
            return ConvertUtil.convertList(queryExhibitionSettlementDetailOfBuilder(query).getExhibitionSettlementDetail(), ServiceBookingVO.class);
        } else {
            ExhibitionSettlementDTO query = new ExhibitionSettlementDTO();
            query.setCompanyId(exhibitionSettlement.getCompanyId());
            query.setCompanyType(exhibitionSettlement.getCompanyType());
            query.setExhibitionManageId(exhibitionSettlement.getExhibitionManageId());
            return ConvertUtil.convertList(queryExhibitionSettlementDetail(query).getExhibitionSettlementDetail(), ServiceBookingVO.class);
        }
    }

    @Override
    public Boolean applyForSettlement(ExhibitionSettlementDTO dto) {
        // 校验是否已经申请，或已结算
        List<ExhibitionSettlement> list = list(new QueryWrapper<ExhibitionSettlement>().lambda()
                .eq(ExhibitionSettlement::getIsDeleted, BusinessConstant.NO)
                .eq(ExhibitionSettlement::getCompanyId, dto.getCompanyId())
                .eq(ExhibitionSettlement::getSpaceCode, dto.getSpaceCode())
                .eq(ExhibitionSettlement::getSiteCode, dto.getSiteCode())
                .in(ExhibitionSettlement::getSettleStatus, Arrays.asList(ExhibitionSettlementSettleStatusEnum.REQUESTED, ExhibitionSettlementSettleStatusEnum.HAS_SETTLE))
        );
        if(CollectionUtils.isNotEmpty(list)){
            if (list.get(0).getSettleStatus().eq(ExhibitionSettlementSettleStatusEnum.REQUESTED)) {
                throw BizException.wrap(VenueServiceExceptionCode.SETTLEMENT_REQUESTED);
            } else {
                throw BizException.wrap(VenueServiceExceptionCode.SETTLEMENT_HAS_SETTLE);
            }
        }
        boolean b = save(BeanUtil.copyProperties(dto, ExhibitionSettlement.class, COMMON_IGNORE_PROPERTIES));
        // 更新展商表状态
        ExhibitorDTO exhibitorDTO = new ExhibitorDTO();
        exhibitorDTO.setId(dto.getId());
        exhibitorDTO.setSettleStatus(ExhibitorSettleStatusEnum.REQUESTED);
        exhibitorFeign.updateExhibitor(exhibitorDTO);
        return b;
    }

    @Override
    public ExhibitionSettlementVO queryExhibitionSettlementDetail(ExhibitionSettlementDTO query) {
        ExhibitionSettlement exhibitionSettlement = null;
        // 判断是否有生成记录
        if (Objects.nonNull(query.getId())) {
            exhibitionSettlement = this.getById(query.getId());
        } else if (Objects.nonNull(query.getExhibitionManageId()) && Objects.nonNull(query.getCompanyId())) {
            exhibitionSettlement = getOne(new QueryWrapper<ExhibitionSettlement>()
                    .lambda().eq(ExhibitionSettlement::getIsDeleted, BusinessConstant.DELETE_NO)
                    .eq(ExhibitionSettlement::getExhibitionManageId, query.getExhibitionManageId())
                    .eq(ExhibitionSettlement::getCompanyType, ExhibitionSettlementCompanyTypeEnum.HOME_SERVICE_PROVIDER)
                    .eq(ExhibitionSettlement::getCompanyId, query.getCompanyId()));
        }
        // 处理主场的结算明细
        return getExhibitionSettlementOfHome(query, exhibitionSettlement);
    }

    @Override
    public ExhibitionSettlementVO queryWaitVenueExhibitionSettlement(ExhibitionSettlementDTO query) {
        log.info("queryWaitVenueExhibitionSettlement - 查询场馆待结算的结算单, query={}", query);
        ExhibitionSettlementVO exhibitionSettlementVO = new ExhibitionSettlementVO();
        BeanUtil.copyProperties(query,exhibitionSettlementVO);
        BigDecimal totalDiscountAmount = BigDecimal.ZERO;
        exhibitionSettlementVO.setDiscountAmount(totalDiscountAmount);
        BigDecimal totalReceived = BigDecimal.ZERO;
        exhibitionSettlementVO.setReceived(totalReceived);
        BigDecimal totalHasInvoicedAmount = BigDecimal.ZERO;
        exhibitionSettlementVO.setInvoicedAmount(totalHasInvoicedAmount);
        BigDecimal totalBondManage = BigDecimal.ZERO;
        exhibitionSettlementVO.setBondAmount(totalBondManage);
        BigDecimal totalPayableBondAmount = BigDecimal.ZERO;
        exhibitionSettlementVO.setPayableBondAmount(totalPayableBondAmount);
        BigDecimal totalViolationPunish = BigDecimal.ZERO;
        exhibitionSettlementVO.setViolationPunish(totalViolationPunish);
        List<ExhibitionSettlementDetailVO> exhibitionSettlementDetailAllList = new ArrayList<>();
        exhibitionSettlementVO.setExhibitionSettlementDetail(exhibitionSettlementDetailAllList);
        // 计算主场服务订单（现场预定）的结算
        ExhibitionSettlementVO venueServiceOrderSettlement = homeServiceOrderService.getVenueServiceOrderSettlement(query);
        calculateExhibitionSettlement(exhibitionSettlementVO, venueServiceOrderSettlement);
        // 计算场馆报修订单的结算
        ExhibitionSettlementVO venueRepairOrderSettlement = venueRepairServiceOrderService.getVenueRepairSettlement(query);
        calculateExhibitionSettlement(exhibitionSettlementVO, venueRepairOrderSettlement);
        // 计算场馆加班单的结算单
        ExhibitionSettlementVO venueWorkOvertimeSettlement = workOvertimeService.getVenueWorkOvertimeSettlement(query);
        calculateExhibitionSettlement(exhibitionSettlementVO, venueWorkOvertimeSettlement);
        // 计算主场报馆的结算
        List<ExhibitionSettlementDetailVO> exhibitionSettlementDetailOfReport = baseMapper.queryExhibitionSettlementDetailOfReport(query);
        if(CollectionUtils.isNotEmpty(exhibitionSettlementDetailOfReport)){
            exhibitionSettlementDetailAllList.addAll(exhibitionSettlementDetailOfReport);
        }
        // 计算应付保证金和已支付保证金
        ExhibitionSettlementVO venueBondManageSettlement = bondManageService.getVenueBondManageSettlement(query);
        if (venueBondManageSettlement != null) {
            BigDecimal bondAmount = venueBondManageSettlement.getBondAmount() == null ? BigDecimal.ZERO : venueBondManageSettlement.getBondAmount();
            totalBondManage = totalBondManage.add(bondAmount);
            BigDecimal payableBondAmount = venueBondManageSettlement.getPayableBondAmount() == null ? BigDecimal.ZERO : venueBondManageSettlement.getPayableBondAmount();
            totalPayableBondAmount = totalPayableBondAmount.add(payableBondAmount);
        }
        exhibitionSettlementVO.setBondAmount(totalBondManage);
        exhibitionSettlementVO.setPayableBondAmount(totalPayableBondAmount);
        // 计算违规罚款
        ExhibitionSettlementVO venueViolationRecordSettlement = violationRecordService.getVenueViolationRecordSettlement(query);
        if (venueViolationRecordSettlement != null) {
            BigDecimal violationPunish = venueViolationRecordSettlement.getViolationPunish() == null ? BigDecimal.ZERO : venueViolationRecordSettlement.getViolationPunish();
            totalViolationPunish = totalViolationPunish.add(violationPunish);
        }
        exhibitionSettlementVO.setViolationPunish(totalViolationPunish);
        return exhibitionSettlementVO;
    }

    @Override
    public ExhibitionSettlementVO queryWaitHomeExhibitionSettlement(ExhibitionSettlementDTO query) {
        log.info("queryWaitHomeExhibitionSettlement - 查询主场待结算的结算单, query={}", query);
        ExhibitionSettlementVO exhibitionSettlementVO = new ExhibitionSettlementVO();
        BeanUtil.copyProperties(query,exhibitionSettlementVO);
        BigDecimal totalDiscountAmount = BigDecimal.ZERO;
        exhibitionSettlementVO.setDiscountAmount(totalDiscountAmount);
        BigDecimal totalReceived = BigDecimal.ZERO;
        exhibitionSettlementVO.setReceived(totalReceived);
        BigDecimal totalHasInvoicedAmount = BigDecimal.ZERO;
        exhibitionSettlementVO.setInvoicedAmount(totalHasInvoicedAmount);
        BigDecimal totalBondManage = BigDecimal.ZERO;
        exhibitionSettlementVO.setBondAmount(totalBondManage);
        BigDecimal totalPayableBondAmount = BigDecimal.ZERO;
        exhibitionSettlementVO.setPayableBondAmount(totalPayableBondAmount);
        BigDecimal totalViolationPunish = BigDecimal.ZERO;
        exhibitionSettlementVO.setViolationPunish(totalViolationPunish);
        List<ExhibitionSettlementDetailVO> exhibitionSettlementDetailAllList = new ArrayList<>();
        exhibitionSettlementVO.setExhibitionSettlementDetail(exhibitionSettlementDetailAllList);
        // 计算主场服务订单，管理费订单的结算
        ExhibitionSettlementVO homeServiceOrderSettlement = homeServiceOrderService.getHomeServiceOrderSettlement(query);
        calculateExhibitionSettlement(exhibitionSettlementVO, homeServiceOrderSettlement);
        // 计算主场报修订单的结算
        ExhibitionSettlementVO venueRepairOrderSettlement = homeRepairServiceOrderService.getHomeRepairSettlement(query);
        calculateExhibitionSettlement(exhibitionSettlementVO, venueRepairOrderSettlement);
        // 计算主场加班单的结算单
        ExhibitionSettlementVO venueWorkOvertimeSettlement = workOvertimeService.getHomeWorkOvertimeSettlement(query);
        calculateExhibitionSettlement(exhibitionSettlementVO, venueWorkOvertimeSettlement);
        // 计算应付保证金和已支付保证金
        ExhibitionSettlementVO venueBondManageSettlement = homeBondManageService.getHomeBondManageSettlement(query);
        if (venueBondManageSettlement != null) {
            BigDecimal bondAmount = venueBondManageSettlement.getBondAmount() == null ? BigDecimal.ZERO : venueBondManageSettlement.getBondAmount();
            totalBondManage = totalBondManage.add(bondAmount);
            BigDecimal payableBondAmount = venueBondManageSettlement.getPayableBondAmount() == null ? BigDecimal.ZERO : venueBondManageSettlement.getPayableBondAmount();
            totalPayableBondAmount = totalPayableBondAmount.add(payableBondAmount);
        }
        exhibitionSettlementVO.setBondAmount(totalBondManage);
        exhibitionSettlementVO.setPayableBondAmount(totalPayableBondAmount);
        // 计算违规罚款
        ExhibitionSettlementVO venueViolationRecordSettlement = violationRecordService.getHomeViolationRecordSettlement(query);
        if (venueViolationRecordSettlement != null) {
            BigDecimal violationPunish = venueViolationRecordSettlement.getViolationPunish() == null ? BigDecimal.ZERO : venueViolationRecordSettlement.getViolationPunish();
            totalViolationPunish = totalViolationPunish.add(violationPunish);
        }
        exhibitionSettlementVO.setViolationPunish(totalViolationPunish);
        return exhibitionSettlementVO;
    }

    @Override
    public ExhibitionSettlementVO queryExhibitionSettlementDetailOfBuilder(ExhibitionSettlementDTO query) {
        ExhibitionSettlement exhibitionSettlement = null;
        // 判断是否有生成记录
        if (Objects.nonNull(query.getId())) {
            exhibitionSettlement = this.getById(query.getId());
            BeanUtil.copyProperties(exhibitionSettlement,query);
        } else if (Objects.nonNull(query.getExhibitionManageId()) && Objects.nonNull(query.getCompanyId())) {
            exhibitionSettlement = getOne(new QueryWrapper<ExhibitionSettlement>()
                    .lambda().eq(ExhibitionSettlement::getIsDeleted, BusinessConstant.DELETE_NO)
                    .eq(ExhibitionSettlement::getExhibitionManageId, query.getExhibitionManageId())
                    .eq(ExhibitionSettlement::getCompanyType, query.getCompanyType())
                    .eq(ExhibitionSettlement::getCompanyId, query.getCompanyId())
                    .eq(ExhibitionSettlement::getSiteCode, query.getSiteCode())
                    .eq(ExhibitionSettlement::getSpaceCode, query.getSpaceCode()));
        }
        // 处理搭建商的结算明细
        return getExhibitionSettlementOfBuilder(query, exhibitionSettlement);
    }

    @Override
    public Boolean cancelSettlementServiceItem(ExhibitionSettlementDTO dto) {
        // 取消服务预定项
        return serviceBookingService.cancelSettlementServiceItem(dto.getId());
    }

    @Override
    public Boolean generateSettlement(ExhibitionSettlementDTO dto) {
        dto.setSettlementAmount(dto.getReceivables());
        dto.setRefundAmount(BigDecimal.ZERO);
        // 生成结算单号
        String settlementNo = CreatCode.creatCode(baseMapper, SETTLEMENT_NO, 8, JS);
        List<ExhibitionSettlementDetailDTO> exhibitionSettlementDetail = dto.getExhibitionSettlementDetail();
        // 生成结算单
        ExhibitionSettlement exhibitionSettlement = BeanUtil.copyProperties(dto, ExhibitionSettlement.class);
        exhibitionSettlement.setSettlementNo(settlementNo);
        exhibitionSettlement.setSettleStatus(ExhibitionSettlementSettleStatusEnum.HAS_SETTLE);
        exhibitionSettlement.setSettlementTime(LocalDateTime.now());
        boolean flag = save(exhibitionSettlement);
        List<ExhibitionSettlementDetail> exhibitionSettlementDetails = new ArrayList<>();
        for (ExhibitionSettlementDetailDTO exhibitionSettlementDetailDTO : exhibitionSettlementDetail) {
            exhibitionSettlementDetailDTO.setSettlementNo(settlementNo);
            exhibitionSettlementDetails.add(BeanUtil.copyProperties(exhibitionSettlementDetailDTO,ExhibitionSettlementDetail.class,BusinessConstant.BUSINESS_COMMON));
        }
        exhibitionSettlementDetailService.saveBatch(exhibitionSettlementDetails);
        saveTransactionOrder(exhibitionSettlement);
        return flag;
    }

    public boolean saveTransactionOrder(ExhibitionSettlement exhibitionSettlement) {
        log.info("saveTransactionOrder - 生成支付系统交易订单, exhibitionSettlement={}", exhibitionSettlement);
        TransactionOrderDTO transactionOrderDTO = new TransactionOrderDTO();
        transactionOrderDTO.setExhibitionId(exhibitionSettlement.getExhibitionManageId());
        ExhibitionManage exhibitionManage = exhibitionManageService.getById(exhibitionSettlement.getExhibitionManageId());
        transactionOrderDTO.setExhibitionName(exhibitionManage.getExhibitionName());
        transactionOrderDTO.setOrderType(TransactionOrderOrderTypeEnum.SERVICE);
        transactionOrderDTO.setOrderNum(exhibitionSettlement.getSettlementNo());
        transactionOrderDTO.setOrderAmount(exhibitionSettlement.getSettlementAmount());
        transactionOrderDTO.setOrderTime(exhibitionSettlement.getSettlementTime());
        transactionOrderDTO.setOrderStatus(TransactionOrderOrderStatusEnum.UNPAY);
        transactionOrderDTO.setPayer(exhibitionSettlement.getCompanyName());
        transactionOrderDTO.setPaymentPeriods(1);
        if (exhibitionSettlement.getCompanyType().eq(ExhibitionSettlementCompanyTypeEnum.BUILD_SERVICE_PROVIDER)) {
            transactionOrderDTO.setSystemCode(MenuAffiliationEnum.P_COMPOSITE_COURT.getCode());
            // 查询主场
            ExhibitionServiceProviderQuery exhibitionServiceProviderQuery = new ExhibitionServiceProviderQuery();
            exhibitionServiceProviderQuery.setExhibitionManageId(exhibitionSettlement.getExhibitionManageId());
            exhibitionServiceProviderQuery.setServiceProviderType(ServiceProviderTypeEnum.HOME_SERVICE_PROVIDER.getCode());
            List<ServiceProviderVO> serviceProviderVOS = exhibitionServiceProviderService.queryExhibitionServiceProvider(exhibitionServiceProviderQuery);
            if (CollectionUtils.isNotEmpty(serviceProviderVOS)) {
                transactionOrderDTO.setPayee(serviceProviderVOS.get(0).getCompanyName());
            }
        } else if(!exhibitionSettlement.getCompanyType().eq(ExhibitionSettlementCompanyTypeEnum.MATCHING_SERVICE_PROVIDER)){
            transactionOrderDTO.setSystemCode(MenuAffiliationEnum.P_VENUE.getCode());
            transactionOrderDTO.setPayee(venueManagePayee);
        }
        return venueManageTransactionOrderService.save(transactionOrderDTO);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean generateSettlementForBuilder(ExhibitionSettlementDTO dto) {
        // 校验结算状态
        R<List<ExhibitorVO>> listR = checkSettleStatus(dto);
        dto.setSettlementAmount(dto.getReceivables());
        dto.setRefundAmount(BigDecimal.ZERO);
        // 生成结算单号
        String settlementNo = CreatCode.creatCode(baseMapper, SETTLEMENT_NO, 8, JS);
        List<ExhibitionSettlementDetailDTO> exhibitionSettlementDetail = dto.getExhibitionSettlementDetail();
        // 更新结算单
        ExhibitionSettlement exhibitionSettlement = BeanUtil.copyProperties(dto, ExhibitionSettlement.class);
        exhibitionSettlement.setSettlementNo(settlementNo);
        exhibitionSettlement.setSettlementTime(LocalDateTime.now());
        exhibitionSettlement.setSettleStatus(ExhibitionSettlementSettleStatusEnum.HAS_SETTLE);
        boolean b = updateById(exhibitionSettlement);
        for (ExhibitionSettlementDetailDTO exhibitionSettlementDetailDTO : exhibitionSettlementDetail) {
            exhibitionSettlementDetailDTO.setSettlementNo(settlementNo);
            exhibitionSettlementDetailService.save(BeanUtil.copyProperties(exhibitionSettlementDetailDTO,ExhibitionSettlementDetail.class,BusinessConstant.BUSINESS_COMMON));
        }
        saveTransactionOrder(getById(exhibitionSettlement.getId()));
        // 更新结算状态
        for (ExhibitorVO exhibitorVO : listR.getData()) {
            ExhibitorDTO exhibitorDTO = BeanUtil.copyProperties(exhibitorVO, ExhibitorDTO.class);
            exhibitorDTO.setSettleStatus(ExhibitorSettleStatusEnum.HAS_SETTLE);
            exhibitorFeign.updateExhibitor(exhibitorDTO);
        }
        return b;
    }

    /**
     * 校验结算状态
     * @param dto
     * @return
     */
    private R<List<ExhibitorVO>> checkSettleStatus(ExhibitionSettlementDTO dto) {
        ExhibitorDTO exhibitorDTO = new ExhibitorDTO();
        exhibitorDTO.setSiteCode(dto.getSiteCode());
        R<List<ExhibitorVO>> listR = exhibitorFeign.queryExhibitors(exhibitorDTO);
        for (ExhibitorVO exhibitorVO : listR.getData()) {
            if(exhibitorVO.getSettleStatus().eq(ExhibitorSettleStatusEnum.HAS_SETTLE)){
                throw BizException.wrap(VenueServiceExceptionCode.SETTLEMENT_HAS_SETTLE);
            }
        }
        return listR;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean settlementCollect(ExhibitionSettlementDTO dto) {
        ExhibitionSettlement exhibitionSettlement = this.getOne(new QueryWrapper<ExhibitionSettlement>().lambda()
                .eq(ExhibitionSettlement::getCompanyId, dto.getCompanyId())
                .eq(ExhibitionSettlement::getCompanyType, dto.getCompanyType())
                .eq(StringUtils.isNotBlank(dto.getSpaceCode()), ExhibitionSettlement::getSpaceCode, dto.getSpaceCode())
                .eq(StringUtils.isNotBlank(dto.getSiteCode()), ExhibitionSettlement::getSiteCode, dto.getSiteCode())
                .eq(ExhibitionSettlement::getIsDeleted, BusinessConstant.NO));
        if (Objects.isNull(exhibitionSettlement)) {
            exhibitionSettlement = BeanUtil.copyProperties(dto, ExhibitionSettlement.class);
            exhibitionSettlement.setReceived(dto.getCollectAmount());
            // 判断是附加费还是服务费
            if (dto.getCollectType().equals(SettlementCollectTypeEnum.SERVICE.getCode())) {
                exhibitionSettlement.setServiceReceived(dto.getCollectAmount());
            } else if (dto.getCollectType().equals(SettlementCollectTypeEnum.SURCHARGE.getCode())) {
                exhibitionSettlement.setSurchargeReceived(dto.getCollectAmount());
            }
            save(exhibitionSettlement);
        } else {
            ExhibitionSettlement updateEntity = new ExhibitionSettlement();
            updateEntity.setId(exhibitionSettlement.getId());
            updateEntity.setReceived(exhibitionSettlement.getReceived().add(dto.getCollectAmount()));
            // 判断是附加费还是服务费
            if (dto.getCollectType().equals(SettlementCollectTypeEnum.SERVICE.getCode())) {
                exhibitionSettlement.setServiceReceived(exhibitionSettlement.getServiceReceived().add(dto.getCollectAmount()));
                exhibitionSettlement.setServiceReceivables(exhibitionSettlement.getTotalServicePrice().subtract(exhibitionSettlement.getServiceReceived()).compareTo(BigDecimal.ZERO) > 0 ? exhibitionSettlement.getTotalServicePrice().subtract(exhibitionSettlement.getServiceReceived()) : BigDecimal.ZERO);
                updateEntity.setServiceReceived(exhibitionSettlement.getServiceReceived());
                updateEntity.setServiceReceivables(exhibitionSettlement.getServiceReceivables());

            } else if (dto.getCollectType().equals(SettlementCollectTypeEnum.SURCHARGE.getCode())) {
                exhibitionSettlement.setSurchargeReceived(exhibitionSettlement.getSurchargeReceived().add(dto.getCollectAmount()));
                exhibitionSettlement.setSurchargeReceivables(exhibitionSettlement.getTotalSurcharge().subtract(exhibitionSettlement.getSurchargeReceived()).compareTo(BigDecimal.ZERO) > 0 ? exhibitionSettlement.getTotalSurcharge().subtract(exhibitionSettlement.getSurchargeReceived()) : BigDecimal.ZERO);
                updateEntity.setSurchargeReceived(exhibitionSettlement.getSurchargeReceived());
                updateEntity.setSurchargeReceivables(exhibitionSettlement.getSurchargeReceivables());

            }

            // 判断认领的钱是否超过了应收款
            if (exhibitionSettlement.getReceivables().compareTo(dto.getCollectAmount()) >= 0) {
                updateEntity.setReceivables(exhibitionSettlement.getReceivables().subtract(dto.getCollectAmount()));
            } else {
                // 超过的部分属于应退款金额
                updateEntity.setRefundAmount(exhibitionSettlement.getRefundAmount().add(dto.getCollectAmount().subtract(exhibitionSettlement.getReceivables())));
                updateEntity.setReceivables(BigDecimal.ZERO);
            }
            updateEntity.setInvoicedAmount(updateEntity.getReceived().subtract(updateEntity.getRefundAmount() == null ? BigDecimal.ZERO : updateEntity.getRefundAmount()).subtract(exhibitionSettlement.getHasInvoicedAmount()));
            updateById(updateEntity);
        }
        // 更新收款记录
        PaymentRecordDTO paymentRecordDTO = new PaymentRecordDTO();
        paymentRecordDTO.setId(dto.getPaymentRecordId());
        paymentRecordDTO.setCollectAmount(dto.getCollectAmount());
        paymentRecordDTO.setBusinessCode(exhibitionSettlement.getSettlementNo());
        paymentRecordFeign.settlementCollect(paymentRecordDTO);
        // 交易记录
        generateTransaction(dto, exhibitionSettlement);
        return true;
    }

    private void generateTransaction(ExhibitionSettlementDTO dto, ExhibitionSettlement exhibitionSettlement) {
        TransactionDTO transactionDTO = new TransactionDTO();
        transactionDTO.setExhibitionId(exhibitionSettlement.getExhibitionManageId());
        ExhibitionManage exhibitionManage = exhibitionManageService.getById(exhibitionSettlement.getExhibitionManageId());
        transactionDTO.setExhibitionName(Objects.nonNull(exhibitionManage) ? exhibitionManage.getExhibitionName() : Strings.EMPTY);
        transactionDTO.setSpaceName(exhibitionSettlement.getSpaceName());
        transactionDTO.setSiteName(exhibitionSettlement.getSiteName());
        transactionDTO.setServiceProviderId(exhibitionSettlement.getCompanyId());
        transactionDTO.setServiceProviderName(exhibitionSettlement.getCompanyName());
        transactionDTO.setServiceProviderType(exhibitionSettlement.getCompanyType().getCode());
        transactionDTO.setOrderType(InvoiceApplyBusinessTypeEnum.J.getCode());
        transactionDTO.setOrderNum(exhibitionSettlement.getSettlementNo());
        transactionDTO.setOrderAmount(dto.getCollectAmount());
        transactionDTO.setOrderTime(LocalDateTime.now());
        transactionDTO.setTransactionType(TranstionTypeEnum.PAYED.getCode());
        transactionDTO.setTransactionState(TransactionStatusEnum.PAYED.getCode());
        transactionDTO.setPayer(dto.getPayer());
        transactionDTO.setPayType(PayTypeEnum.TRANSFER_ACCOUNT.getCode());
        transactionDTO.setSystemScene(ContextUtil.getSystemScene());
        transactionFeign.save(transactionDTO);
    }

    @Override
    public Boolean updateSettlement(ExhibitionSettlementDTO dto) {
        ExhibitionSettlement exhibitionSettlement = BeanUtil.copyProperties(dto, ExhibitionSettlement.class);
        ExhibitionSettlement settlement = getById(dto.getId());
        ExhibitionManage exhibitionManage = exhibitionManageService.getById(settlement.getExhibitionManageId());
        String exhibitionName = Objects.nonNull(exhibitionManage) ? exhibitionManage.getExhibitionName() : Strings.EMPTY;
        // 判断是否是申请开票推送站内信
        if (Objects.nonNull(dto.getInvoicingStatus())
                && dto.getInvoicingStatus().equals(ExhibitionSettlementInvoicingStatusEnum.REQUESTED.getCode())) {
            String content = String.format("有新的发票申请需要审核，单号：%s，展会名称：%s，申请人：%s", settlement.getSettlementNo(), exhibitionName, settlement.getCompanyName());
            threadPoolTaskExecutor.execute(() -> {
                // 判断是否是搭建商结算
                sengInnerMsg(settlement, content);
            });
        }
        // 判断是否是申请退款推送站内信
        if (Objects.nonNull(dto.getRefundStatus())
                && dto.getRefundStatus().eq(ExhibitionSettlementRefundStatusEnum.REQUESTED)) {
            String content = String.format("有新的退款申请需要审核，单号：%s，展会名称：%s，申请人：%s", settlement.getSettlementNo(), exhibitionName, settlement.getCompanyName());
            threadPoolTaskExecutor.execute(() -> {
                sengInnerMsg(settlement, content);
            });
        }
        // 处理开票金额
        dealInvoicedAmount(settlement,exhibitionSettlement);
        return updateById(exhibitionSettlement);
    }

    @Override
    public Boolean updateBizRefundState(BizStateDTO bizStateDTO) {
        ExhibitionSettlement exhibitionSettlement = getById(bizStateDTO.getId());
        if (Objects.nonNull(exhibitionSettlement)) {
            ExhibitionSettlement updateEntity = new ExhibitionSettlement();
            updateEntity.setId(exhibitionSettlement.getId());
            // 审核状态
            String examineState = bizStateDTO.getExamineState();
            PayApproveStateEnum payApproveStateEnum = PayApproveStateEnum.get(examineState);
            if (payApproveStateEnum.eq(PayApproveStateEnum.PAY_NOT_APPROVED)) {
                // 被驳回
                updateEntity.setRefundStatus(ExhibitionSettlementRefundStatusEnum.REJECTED);
                updateById(updateEntity);
            } else if (payApproveStateEnum.eq(PayApproveStateEnum.PAY_APPROVED)) {
                // 审核通过
                updateEntity.setRefundStatus(ExhibitionSettlementRefundStatusEnum.REFUNDING);
                updateById(updateEntity);
            }
        }
        return true;
    }

    @Override
    public Boolean updateBizInvoiceApplyState(BizStateDTO bizStateDTO) {
        ExhibitionSettlement exhibitionSettlement = getById(bizStateDTO.getId());
        if (Objects.nonNull(exhibitionSettlement)) {
            ExhibitionSettlement updateEntity = new ExhibitionSettlement();
            updateEntity.setId(exhibitionSettlement.getId());
            // 审核状态
            String examineState = bizStateDTO.getExamineState();
            PayApproveStateEnum payApproveStateEnum = PayApproveStateEnum.get(examineState);
            if (payApproveStateEnum.eq(PayApproveStateEnum.PAY_NOT_APPROVED)) {
                // 被驳回
                updateEntity.setInvoicingStatus(ExhibitionSettlementInvoicingStatusEnum.REJECTED);
                updateById(updateEntity);
            } else if (payApproveStateEnum.eq(PayApproveStateEnum.PAY_APPROVED)) {
                // 审核通过
                updateEntity.setInvoicingStatus(ExhibitionSettlementInvoicingStatusEnum.INVOICING);
                updateById(updateEntity);
            }
        }
        return true;
    }

    @Override
    public void checkSettleState(ExhibitionSettlementDTO exhibitionSettlementDTO) {
        List<ExhibitionSettlement> list = list(new QueryWrapper<ExhibitionSettlement>().lambda()
                .eq(ExhibitionSettlement::getIsDeleted, BusinessConstant.NO)
                .in(ExhibitionSettlement::getSettleStatus, Arrays.asList(ExhibitionSettlementSettleStatusEnum.REQUESTED, ExhibitionSettlementSettleStatusEnum.REQUESTED))
                .eq(ExhibitionSettlement::getExhibitionManageId, exhibitionSettlementDTO.getExhibitionManageId())
                .eq(ExhibitionSettlement::getCompanyType, ExhibitionSettlementCompanyTypeEnum.BUILD_SERVICE_PROVIDER)
                .eq(Objects.nonNull(exhibitionSettlementDTO.getSpaceCode()), ExhibitionSettlement::getSpaceCode, exhibitionSettlementDTO.getSpaceCode())
                .eq(Objects.nonNull(exhibitionSettlementDTO.getSpaceName()), ExhibitionSettlement::getSpaceName, exhibitionSettlementDTO.getSpaceName())
                .eq(Objects.nonNull(exhibitionSettlementDTO.getSiteName()), ExhibitionSettlement::getSiteName, exhibitionSettlementDTO.getSiteName())
                .eq(Objects.nonNull(exhibitionSettlementDTO.getSiteCode()), ExhibitionSettlement::getSiteCode, exhibitionSettlementDTO.getSiteCode()));
        for (ExhibitionSettlement exhibitionSettlement : list) {
            if (exhibitionSettlement.getSettleStatus().eq(ExhibitionSettlementSettleStatusEnum.REQUESTED)) {
                throw BizException.wrap(VenueServiceExceptionCode.SETTLEMENT_REQUESTED);
            } else if (exhibitionSettlement.getSettleStatus().eq(ExhibitionSettlementSettleStatusEnum.HAS_SETTLE)) {
                throw BizException.wrap(VenueServiceExceptionCode.SETTLEMENT_HAS_SETTLE);
            }
        }
    }

    private void dealInvoicedAmount(ExhibitionSettlement settlement, ExhibitionSettlement exhibitionSettlement) {
        if (Objects.nonNull(exhibitionSettlement.getInvoicingStatus())) {
            if(exhibitionSettlement.getInvoicingStatus().eq(ExhibitionSettlementInvoicingStatusEnum.INVOICED)){
                //如果是已处理，修改已开票金额为应开票金额
                exhibitionSettlement.setHasInvoicedAmount(settlement.getInvoicedAmount());
            }else if(exhibitionSettlement.getInvoicingStatus().eq(ExhibitionSettlementInvoicingStatusEnum.INVOICE_RED)){
                //如果是已处理，修改已开票金额为0
                exhibitionSettlement.setHasInvoicedAmount(BigDecimal.ZERO);
            }
        }
    }

    private void sengInnerMsg(ExhibitionSettlement settlement, String content) {
        if(settlement.getCompanyType().eq(ExhibitionSettlementCompanyTypeEnum.BUILD_SERVICE_PROVIDER)){
            // 查询主场id
            ExhibitionServiceProviderQuery exhibitionServiceProviderQuery = new ExhibitionServiceProviderQuery();
            exhibitionServiceProviderQuery.setExhibitionManageId(settlement.getExhibitionManageId());
            exhibitionServiceProviderQuery.setServiceProviderType(ServiceProviderTypeEnum.HOME_SERVICE_PROVIDER.getCode());
            List<ServiceProviderVO> serviceProviderVOS = exhibitionServiceProviderService.queryExhibitionServiceProvider(exhibitionServiceProviderQuery);
            for (ServiceProviderVO serviceProviderVO : serviceProviderVOS) {
                homeMsgFeign.sendInnerMsgByTeamId(content,serviceProviderVO.getId());
            }
        }else {
            sendMsgUtil.sendInnerMsg(content, StaticContextUtil.getProjectSystemScene());
        }
    }

    /**
     * 处理主运和主场的结算明细
     *
     * @param query
     * @param exhibitionSettlement
     * @return
     */
    private ExhibitionSettlementVO getExhibitionSettlementOfHome(ExhibitionSettlementDTO query, ExhibitionSettlement exhibitionSettlement) {
        ExhibitionSettlementVO exhibitionSettlementVO = Objects.nonNull(exhibitionSettlement) ? BeanUtil.copyProperties(exhibitionSettlement, ExhibitionSettlementVO.class) : new ExhibitionSettlementVO();
        // 判断是否已经生成结算单
        if (Objects.nonNull(exhibitionSettlement)) {
            // 查询结算明细
            List<ExhibitionSettlementDetail> list = exhibitionSettlementDetailService.list(new QueryWrapper<ExhibitionSettlementDetail>().lambda()
                    .eq(ExhibitionSettlementDetail::getIsDeleted, BusinessConstant.NO)
                    .eq(ExhibitionSettlementDetail::getSettlementNo, exhibitionSettlement.getSettlementNo()));
            exhibitionSettlementVO.setExhibitionSettlementDetail(ConvertUtil.convertList(list,ExhibitionSettlementDetailVO.class));
        }else {
            exhibitionSettlementVO = queryWaitVenueExhibitionSettlement(query);
            dealAmount(exhibitionSettlementVO);
        }
        return exhibitionSettlementVO;
    }

    /**
     * 处理主运和主场的结算明细
     *
     * @param query
     * @param exhibitionSettlement
     * @return
     */
    private ExhibitionSettlementVO getExhibitionSettlementOfBuilder(ExhibitionSettlementDTO query, ExhibitionSettlement exhibitionSettlement) {
        ExhibitionSettlementVO exhibitionSettlementVO = Objects.nonNull(exhibitionSettlement) ? BeanUtil.copyProperties(exhibitionSettlement, ExhibitionSettlementVO.class) : new ExhibitionSettlementVO();
        // 判断是否已经生成结算单
        if (Objects.nonNull(exhibitionSettlement) && exhibitionSettlement.getSettleStatus().eq(ExhibitionSettlementSettleStatusEnum.HAS_SETTLE)) {
            // 查询结算明细
            List<ExhibitionSettlementDetail> list = exhibitionSettlementDetailService.list(new QueryWrapper<ExhibitionSettlementDetail>().lambda()
                    .eq(ExhibitionSettlementDetail::getIsDeleted, BusinessConstant.NO)
                    .eq(ExhibitionSettlementDetail::getSettlementNo, exhibitionSettlement.getSettlementNo()));
            exhibitionSettlementVO.setExhibitionSettlementDetail(ConvertUtil.convertList(list,ExhibitionSettlementDetailVO.class));
        }else {
            exhibitionSettlementVO = queryWaitHomeExhibitionSettlement(query);
            dealAmount(exhibitionSettlementVO);
        }
        return exhibitionSettlementVO;
    }

    private void dealAmount(ExhibitionSettlementVO exhibitionSettlementVO) {
        List<ExhibitionSettlementDetailVO> exhibitionSettlementDetail = exhibitionSettlementVO.getExhibitionSettlementDetail();
        // 小记金额
        BigDecimal totalServicePrice = exhibitionSettlementDetail.stream().map(ExhibitionSettlementDetailVO::getSubtotalPrice).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP);
        exhibitionSettlementVO.setTotalServicePrice(totalServicePrice);
        // 附加费合计
        BigDecimal totalSurcharge = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        exhibitionSettlementVO.setTotalSurcharge(totalSurcharge);
        // 保证金应缴金额
        exhibitionSettlementVO.setPayableBondAmount(Objects.nonNull(exhibitionSettlementVO.getPayableBondAmount())?exhibitionSettlementVO.getPayableBondAmount():BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        // 罚款金额
        exhibitionSettlementVO.setViolationPunish(Objects.nonNull(exhibitionSettlementVO.getViolationPunish())?exhibitionSettlementVO.getViolationPunish():BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        // 优惠金额
        exhibitionSettlementVO.setDiscountAmount(Objects.nonNull(exhibitionSettlementVO.getDiscountAmount())?exhibitionSettlementVO.getDiscountAmount():BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        // 合计应收金额 = 小记金额+罚款金额-优惠金额
        BigDecimal totalReceivables = totalServicePrice.add(exhibitionSettlementVO.getViolationPunish()).subtract(exhibitionSettlementVO.getDiscountAmount());
        exhibitionSettlementVO.setTotalReceivables(totalReceivables.setScale(2, RoundingMode.HALF_UP));
        // 已付款金额
        exhibitionSettlementVO.setReceived(Objects.nonNull(exhibitionSettlementVO.getReceived())?exhibitionSettlementVO.getReceived():BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        // 保证金实缴金额
        exhibitionSettlementVO.setBondAmount(Objects.nonNull(exhibitionSettlementVO.getBondAmount())?exhibitionSettlementVO.getBondAmount():BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        // 已开票金额
        exhibitionSettlementVO.setHasInvoicedAmount(Objects.nonNull(exhibitionSettlementVO.getHasInvoicedAmount())?exhibitionSettlementVO.getHasInvoicedAmount():BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        // 应开票金额=合计应收金额-已开票金额
        exhibitionSettlementVO.setInvoicedAmount(exhibitionSettlementVO.getTotalReceivables().subtract(exhibitionSettlementVO.getHasInvoicedAmount()));
        // 应付款金额=合计应收金额-已付款金额-保证金实缴金额；
        exhibitionSettlementVO.setReceivables(exhibitionSettlementVO.getTotalReceivables().subtract(exhibitionSettlementVO.getReceived()).subtract(exhibitionSettlementVO.getBondAmount()));
        // 如果应付款金额小于0 则应退款金额=-应付款金额
        if(exhibitionSettlementVO.getReceivables().compareTo(BigDecimal.ZERO)<0){
            exhibitionSettlementVO.setRefundAmount(exhibitionSettlementVO.getReceivables().multiply(BigDecimal.valueOf(-1)));
            exhibitionSettlementVO.setReceivables(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        }else {
            exhibitionSettlementVO.setRefundAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        }
        log.info("计算后的结算详情：{}",exhibitionSettlementVO);
    }

    private void dealResult(ArrayList<ExhibitionSettlementVO> exhibitionSettlementVOS, ExhibitionServiceProvider home,  List<ExhibitionSettlement> exhibitionSettlements) {
        for (int i = 0; i < exhibitionSettlements.size(); i++) {
            ExhibitionSettlement exhibitionSettlement = exhibitionSettlements.get(i);
            ExhibitionSettlementCompanyTypeEnum exhibitionSettlementCompanyTypeEnum = null;
            String companyName = null;
            Long companyId = null;
            if (i == 0) {
                exhibitionSettlementCompanyTypeEnum = ExhibitionSettlementCompanyTypeEnum.HOME_SERVICE_PROVIDER;
                if (Objects.nonNull(home)) {
                    companyName = home.getServiceProviderName();
                    companyId = home.getServiceProviderId();
                }
            }
            ExhibitionSettlementVO exhibitionSettlementVO;
            if (Objects.isNull(exhibitionSettlement)) {
                exhibitionSettlementVO = new ExhibitionSettlementVO();
                exhibitionSettlementVO.setCompanyType(exhibitionSettlementCompanyTypeEnum);
                // 结算单号
                exhibitionSettlementVO.setSettlementNo(null);
                // 企业名称
                if (Objects.nonNull(companyId)) {
                    exhibitionSettlementVO.setCompanyId(companyId);
                    if (StringUtils.isNotBlank(companyName)) {
                        exhibitionSettlementVO.setCompanyName(companyName);
                    } else {
                        ServiceProvider serviceProvider = serviceProviderService.getById(companyId);
                        if (Objects.nonNull(serviceProvider)) {
                            exhibitionSettlementVO.setCompanyName(serviceProvider.getCompanyName());
                        }
                    }
                    exhibitionSettlementVOS.add(exhibitionSettlementVO);
                }
            } else {
                exhibitionSettlementVO = BeanUtil.copyProperties(exhibitionSettlement, ExhibitionSettlementVO.class);
                exhibitionSettlementVOS.add(exhibitionSettlementVO);
            }
        }
    }

    /**
     * Calculate settlement detail.
     *
     * @param exhibitionSettlementVO the exhibition settlement vo
     * @param businessSettlement     the business settlement
     */
    private static void calculateExhibitionSettlement(ExhibitionSettlementVO exhibitionSettlementVO, ExhibitionSettlementVO businessSettlement) {
        if (businessSettlement == null) {
            return;
        }
        BigDecimal discountAmount = businessSettlement.getDiscountAmount() == null ? BigDecimal.ZERO : businessSettlement.getDiscountAmount();
        BigDecimal totalDiscountAmount = exhibitionSettlementVO.getDiscountAmount() == null ? BigDecimal.ZERO : exhibitionSettlementVO.getDiscountAmount();
        totalDiscountAmount = totalDiscountAmount.add(discountAmount);
        exhibitionSettlementVO.setDiscountAmount(totalDiscountAmount);

        BigDecimal received = businessSettlement.getReceived() == null ? BigDecimal.ZERO : businessSettlement.getReceived();
        BigDecimal totalReceived = exhibitionSettlementVO.getReceived() == null ? BigDecimal.ZERO : exhibitionSettlementVO.getReceived();
        totalReceived = totalReceived.add(received);
        exhibitionSettlementVO.setReceived(totalReceived);

        BigDecimal hasInvoicedAmount = businessSettlement.getHasInvoicedAmount() == null ? BigDecimal.ZERO : businessSettlement.getHasInvoicedAmount();
        BigDecimal totalHasInvoicedAmount = exhibitionSettlementVO.getHasInvoicedAmount() == null ? BigDecimal.ZERO : exhibitionSettlementVO.getHasInvoicedAmount();
        totalHasInvoicedAmount = totalHasInvoicedAmount.add(hasInvoicedAmount);
        exhibitionSettlementVO.setHasInvoicedAmount(totalHasInvoicedAmount);

        List<ExhibitionSettlementDetailVO> allSettlementDetailList = exhibitionSettlementVO.getExhibitionSettlementDetail();
        if (allSettlementDetailList == null) {
            allSettlementDetailList = new ArrayList<>();
        }
        List<ExhibitionSettlementDetailVO> exhibitionSettlementDetailList = businessSettlement.getExhibitionSettlementDetail();
        if (exhibitionSettlementDetailList != null && !exhibitionSettlementDetailList.isEmpty()) {
            allSettlementDetailList.addAll(exhibitionSettlementDetailList);
        }
    }

}
